package com.yima.baseproj.config.argument;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Type;
import java.util.Map;

/**
 * @Author 一码
 * @createDate 2023/4/1 09:00
 * @contact 1424529270@qq.com
 */
@Component
public class MyHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(RequestBodyParam.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        if(methodParameter.hasParameterAnnotation(RequestBodyParam.class)){
            String fieldName = methodParameter.getParameterAnnotation(RequestBodyParam.class).name();

            HttpServletRequest servletRequest = (HttpServletRequest)nativeWebRequest.getNativeRequest(HttpServletRequest.class);

            SafeHttpServletRequestWrapper requestWrapper = new SafeHttpServletRequestWrapper((HttpServletRequest) servletRequest);
            Map<String,Object> map = JSON.parseObject(requestWrapper.getBodyString(),Map.class);
            if(map == null){
                map = (Map<String, Object>) servletRequest.getAttribute("requestBodyParamData");
                if(map == null){
                    return servletRequest.getParameter(fieldName);
                }
                if(map.containsKey(fieldName)){
                    Object value = map.get(fieldName);

                    Type type = methodParameter.getParameter().getType();
                    if(((Class) type).isPrimitive()){
                        return value;
                    }else if(((Class)type).isArray()){
                        return JSON.parseObject(value.toString(),type);
                    }else{
                        if(type.getTypeName().equals(String.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Byte.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Short.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Integer.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Long.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Float.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Double.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Character.class.getTypeName())){
                            return value;
                        }else if(type.getTypeName().equals(Boolean.class.getTypeName())){
                            return value;
                        }else{
                            return JSON.parseObject(((JSONObject)value).toJSONString(),type);
                        }
                    }

                }
            }else{
                servletRequest.setAttribute("requestBodyParamData",map);

                if(map.containsKey(fieldName)){
                    return map.get(fieldName);
                }
            }
        }
        return null;
    }
}
